package com.hsgene.product.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.hsgene.common.ClientType;
import com.hsgene.common.DeleteFlagType;
import com.hsgene.common.util.basic.JsonUtils;
import com.hsgene.common.util.basic.UUID32;
import com.hsgene.common.util.exception.ErrorCode;
import com.hsgene.common.util.qiniu.QiniuCertificateUtil;
import com.hsgene.common.util.result.ApiResult;
import com.hsgene.common.util.result.NullObject;
import com.hsgene.common.util.support.LimitHelper;
import com.hsgene.common.util.support.OrderHelper;
import com.hsgene.common.util.support.Pagination;
import com.hsgene.common.util.validation.FieldChecker;
import com.hsgene.coupon.dto.GeneticDiscountDto;
import com.hsgene.order.domain.applets.AppletsOrderPackageInfoDto;
import com.hsgene.product.condition.CommodityCondition;
import com.hsgene.product.constants.CommodityShelfStatus;
import com.hsgene.product.constants.CommodityStatus;
import com.hsgene.product.domain.GeneticCommodityCategory;
import com.hsgene.product.domain.GeneticTestingPackage;
import com.hsgene.product.domain.GeneticTestingPackageAddtion;
import com.hsgene.product.dto.GeneticTestingCommodityDetailDto;
import com.hsgene.product.dto.GeneticTestingCommodityItemDto;
import com.hsgene.product.dto.tag.CommodityLabelModel;
import com.hsgene.product.dto.wechat.SimpleCommodityDto;
import com.hsgene.product.exception.ProductErrorCode;
import com.hsgene.product.persistence.CommodityRepository;
import com.hsgene.product.service.CommodityCategoryService;
import com.hsgene.product.service.CommodityService;
import com.hsgene.product.service.ProductService;
import com.hsgene.product.service.api.DiscountCouponService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商品服务Impl
 *
 * @author wangbing
 * @version 1.0, 2018/10/11
 */
@Service
public class CommodityServiceImpl implements CommodityService {

    private final static Logger LOGGER = LoggerFactory.getLogger(CommodityServiceImpl.class);

    @Resource
    private CommodityRepository commodityRepository;

    @Resource
    private DiscountCouponService discountCouponService;

    @Resource
    private ProductService productService;

    @Resource
    private CommodityCategoryService commodityCategoryService;

    @Override
    public ApiResult<Pagination<SimpleCommodityDto>> querySimpleCommodity(CommodityCondition condition, OrderHelper
            orderHelper, LimitHelper limitHelper) {
        FieldChecker.checkEmpty(condition, "查询条件");
        FieldChecker.checkEmpty(limitHelper, "分页参数");

        int totalCount = commodityRepository.queryCommodityCount(condition);
        Pagination<SimpleCommodityDto> pagination = Pagination.newInstance(limitHelper, totalCount);
        if (totalCount > 0 && limitHelper.getOffset() <= totalCount) {
            List<SimpleCommodityDto> result = commodityRepository.querySimpleCommodity(condition, orderHelper,
                    limitHelper);
            if (!CollectionUtils.isEmpty(result)) {
                ApiResult<List<GeneticDiscountDto>> discountResult = discountCouponService.queryEffectiveDiscount
                        (ClientType.APPLETS.getCode(), null);
                if (!discountResult.isSucc()) {
                    LOGGER.error(discountResult.getDesc());
                }
                if (!CollectionUtils.isEmpty(discountResult.getData())) {
                    result.forEach(commodity -> commodity.setDiscountTags(
                            discountResult.getData().stream()
                                    .filter(coupon -> coupon.getConditionPrice().compareTo(commodity.getShowPrice()) <= 0)
                                    .map(coupon -> coupon.getConditionPrice().intValue() + "减" + coupon.getDiscountPrice().intValue())
                                    .collect(Collectors.toList()))
                    );
                }
            }
            pagination.setResult(result);
        }

        return ApiResult.succ(pagination);
    }

    @Override
    public ApiResult<Pagination<GeneticTestingCommodityItemDto>> queryCommodityItems(CommodityCondition condition,
                                                                                     OrderHelper orderHelper,
                                                                                     LimitHelper limitHelper) {
        FieldChecker.checkEmpty(condition, "查询条件");
        FieldChecker.checkEmpty(limitHelper, "分页参数");

        int totalCount = commodityRepository.queryCommodityCount(condition);
        Pagination<GeneticTestingCommodityItemDto> pagination = Pagination.newInstance(limitHelper, totalCount);
        if (totalCount > 0 && limitHelper.getOffset() <= totalCount) {
            List<GeneticTestingCommodityItemDto> items = commodityRepository.queryCommodityItems(condition,
                    orderHelper, limitHelper);
            if (!CollectionUtils.isEmpty(items)) {
                int number = limitHelper.getOffset() + 1;
                for (GeneticTestingCommodityItemDto item : items) {
                    item.setNumber(number++);
                }
                pagination.setResult(items);
            }
        }

        return ApiResult.succ(pagination);
    }

    /**
     * @param userId 用户id
     * @return int
     * @description 获取购物车商品数量
     * @author maodi
     * @createDate 2018/10/17 13:40
     */
    @Override
    public int getShoppingCarCommodityCount(String userId) {
        return commodityRepository.getShoppingCarCommodityCount(userId);
    }

    /**
     * @param userId      用户id
     * @param limitHelper 分页条件
     * @return com.hsgene.common.util.support.Pagination<com.hsgene.product.dto.wechat.SimpleCommodityDto>
     * @description 查询当前购物车商品简要信息列表
     * @author maodi
     * @createDate 2018/10/17 11:56
     */
    @Override
    public Pagination<SimpleCommodityDto> getShoppingCarCommodityList(String userId, LimitHelper limitHelper) {
        int totalCount = commodityRepository.getShoppingCarCommodityCount(userId);
        Pagination<SimpleCommodityDto> pagination = Pagination.newInstance(limitHelper, totalCount);
        List<SimpleCommodityDto> result = commodityRepository.getShoppingCarCommodityList(userId, limitHelper);
        dealResult(result);
        pagination.setResult(result);
        return pagination;
    }

    /**
     * @param userId 用户id
     * @param ids    商品id数组
     * @return java.util.List<com.hsgene.product.dto.wechat.SimpleCommodityDto>
     * @description 根据商品id数组获取购物车商品信息
     * @author maodi
     * @createDate 2018/10/17 15:00
     */
    @Override
    public List<SimpleCommodityDto> getShoppingCarCommodityListByIds(String userId, String[] ids) {
        List<SimpleCommodityDto> result = commodityRepository.getShoppingCarCommodityListByIds(userId, ids);
        dealResult(result);
        return result;
    }

    /**
     * @param userId 用户id
     * @param ids    商品id数组
     * @return java.util.Map<java.lang.String , java.lang.Object>
     * @description 根据商品id数组获取购物车商品结算信息
     * @author maodi
     * @createDate 2018/10/17 15:17
     */
    @Override
    public Map<String, Object> getShoppingCarCommodityBalanceByIds(String userId, String[] ids) {
        return commodityRepository.getShoppingCarCommodityBalanceByIds(userId, ids);
    }


    /**
     * @param userId 用户id
     * @param ids    商品id数组
     * @return java.util.List<com.hsgene.order.domain.applets.AppletsOrderPackageInfoDto>
     * @description 根据商品id数组获取小程序订单商品信息
     * @author maodi
     * @createDate 2018/10/18 11:27
     */
    @Override
    public List<AppletsOrderPackageInfoDto> getAppletsOrderPackageInfoDtosByIds(String userId, String[] ids) {
        return commodityRepository.getAppletsOrderPackageInfoDtosByIds(userId, ids);
    }

    /**
     * @param result 查询结果
     * @return void
     * @description 处理查询结果
     * @author maodi
     * @createDate 2018/10/17 14:44
     */
    private void dealResult(List<SimpleCommodityDto> result) {
        if (!CollectionUtils.isEmpty(result)) {
            ApiResult<List<GeneticDiscountDto>> discountResult = discountCouponService.queryEffectiveDiscount
                    (ClientType.APPLETS.getCode(), null);
            if (!discountResult.isSucc()) {
                LOGGER.error(discountResult.getDesc());
            }
            if (!CollectionUtils.isEmpty(discountResult.getData())) {
                List<String> discountTags = discountResult.getData().stream().map(e -> e.getConditionPrice().intValue
                        () + "减" + e.getDiscountPrice().intValue()).collect(Collectors.toList());
                result.forEach(e -> e.setDiscountTags(discountTags));
            }
        }
    }


    @Override
    public ApiResult<Object> findCommodityByPackageId(String packageId) {
        FieldChecker.checkEmpty(packageId, "套餐id");
        // 查询商品套餐信息
        ApiResult<GeneticTestingPackage> packageResult = productService.getPackageById(packageId, null);
        if (!packageResult.isSucc()) {
            return ApiResult.fail(packageResult.getError());
        }
        GeneticTestingPackage packageInfo = packageResult.getData();
        if (packageInfo == null) {
            return ApiResult.fail(ProductErrorCode.COMMODITY_NOT_EXISTED);
        }
        // 查询商品附加信息
        GeneticTestingPackageAddtion packageAddtion = commodityRepository.findByPackageId(packageId);

        return ApiResult.succ(buildCommodityDetail(packageAddtion, packageInfo));
    }


    private GeneticTestingCommodityDetailDto buildCommodityDetail(GeneticTestingPackageAddtion packageAddtion,
                                                                  GeneticTestingPackage packageInfo) {
        GeneticTestingCommodityDetailDto commodity = new GeneticTestingCommodityDetailDto();
        if (packageAddtion == null) {
            // 已添加套餐，但未把套餐加入商品，默认此为不完善的商品，需要运营管理人员完善商品信息
            commodity.setStatus(CommodityStatus.INCOMPLETE.getCode());
            commodity.setShelfStatus(CommodityShelfStatus.OFFLINE.getCode());
            commodity.setDeleteFlag(DeleteFlagType.NOT_DELETED.getCode());
        } else {
            BeanUtils.copyProperties(packageAddtion, commodity);
            if (!StringUtils.isEmpty(packageAddtion.getDetailImagesUrl())) {
                try {
                    commodity.setDetailImagesUrl(JsonUtils.jsonToObject(packageAddtion.getDetailImagesUrl(), new
                            TypeReference<List<String>>() {
                            }));
                } catch (Exception e) {
                    e.printStackTrace();
                    LOGGER.error("商品id = {}的详情图片数据格式异常，不符合JSON格式", packageAddtion.getId());
                    commodity.setDetailImagesUrl(null);
                }
            }
            if (!StringUtils.isEmpty(packageAddtion.getTag())) {
                try {
                    commodity.setTags(JsonUtils.jsonToObject(packageAddtion.getTag(), new
                            TypeReference<List<CommodityLabelModel>>() {
                            }));
                } catch (Exception e) {
                    e.printStackTrace();
                    LOGGER.error("商品id = {}的标签数据格式异常，不符合JSON格式", packageAddtion.getId());
                    commodity.setTags(null);
                }
            }
            if (!StringUtils.isEmpty(packageAddtion.getSuitablePeople())) {
                try {
                    commodity.setSuitablePeople(JsonUtils.jsonToObject(packageAddtion.getSuitablePeople(), new
                            TypeReference<List<CommodityLabelModel>>() {
                            }));
                } catch (Exception e) {
                    e.printStackTrace();
                    LOGGER.error("商品id = {}的适用人群数据格式异常，不符合JSON格式", packageAddtion.getId());
                    commodity.setSuitablePeople(null);
                }
            }
            if (!StringUtils.isEmpty(packageAddtion.getSuitableSex())) {
                try {
                    commodity.setSuitableSex(JsonUtils.jsonToObject(packageAddtion.getSuitableSex(), new TypeReference<List<CommodityLabelModel>>() {
                    }));
                } catch (Exception e) {
                    e.printStackTrace();
                    LOGGER.error("商品id = {}的适用性别数据格式异常，不符合JSON格式", packageAddtion.getId());
                    commodity.setSuitableSex(null);
                }
            }
        }
        commodity.setPackageInfo(packageInfo);
        return commodity;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<NullObject> updateCommodity(GeneticTestingCommodityDetailDto commodityDto) {
        // 参数校验
        FieldChecker.checkEmpty(commodityDto, "商品信息");
        ErrorCode errorCode = commodityDto.checkCommonField();
        if (errorCode != null) {
            return ApiResult.fail(errorCode);
        }
        ApiResult<GeneticCommodityCategory> categoryApiResult = commodityCategoryService.getById(commodityDto
                .getCommodityCategoryId());
        if (!categoryApiResult.isSucc()) {
            return ApiResult.fail(categoryApiResult.getError());
        }
        GeneticCommodityCategory category = categoryApiResult.getData();
        if (category == null || !DeleteFlagType.NOT_DELETED.equals(DeleteFlagType.getEnum(category.getDeleteFlag()))) {
            return ApiResult.fail(ProductErrorCode.COMMODITY_CATEGORY_NOT_EXISTED);
        }
        commodityDto.setCommodityCategoryLabel(category.getCategory());
        GeneticTestingPackageAddtion addtion = commodityRepository.findByPackageId(commodityDto.getPackageInfo()
                .getId());
        if (addtion == null) {
            // 该商品套餐第一次操作信息完善
            addtion = new GeneticTestingPackageAddtion();
            BeanUtils.copyProperties(commodityDto, addtion);
            if (!CollectionUtils.isEmpty(commodityDto.getTags())) {
                addtion.setTag(JsonUtils.objectToJson(commodityDto.getTags()));
            }
            if (!CollectionUtils.isEmpty(commodityDto.getSuitablePeople())) {
                addtion.setSuitablePeople(JsonUtils.objectToJson(commodityDto.getSuitablePeople()));
            }
            if (!CollectionUtils.isEmpty(commodityDto.getSuitableSex())) {
                addtion.setSuitableSex(JsonUtils.objectToJson(commodityDto.getSuitableSex()));
            }
            addtion.setId(UUID32.randomUUIDString());
            addtion.setPackageId(commodityDto.getPackageInfo().getId());
            addtion.setDetailImagesUrl(JsonUtils.objectToJson(commodityDto.getDetailImagesUrl()));
            addtion.setRealPurchaseAmount(0);
            addtion.setShoppingCartAmount(0);
            addtion.setViews(commodityDto.getViews());
            addtion.setCreateDateTime(new Date());
            addtion.setUpdateDateTime(addtion.getCreateDateTime());
            addtion.setFavorableRate(100);
            addtion.setStatus(CommodityStatus.NON_USED.getCode());
            addtion.setShelfStatus(CommodityShelfStatus.OFFLINE.getCode());
            addtion.setDeleteFlag(DeleteFlagType.NOT_DELETED.getCode());
            ApiResult<GeneticTestingPackage> packageResult = productService.updateProduct(commodityDto.getPackageInfo
                    ());
            if (packageResult.isSucc()) {
                // 保存商品信息，累计商品类目使用次数
                commodityRepository.saveCommodity(addtion);
                commodityCategoryService.updateCategoryUsedCount(category.getId(), true);
            } else {
                return ApiResult.fail(packageResult.getError());
            }
        } else {
            // 已完善过，重新修改完善商品信息
            if (DeleteFlagType.DELETE.equals(DeleteFlagType.getEnum(addtion.getDeleteFlag()))) {
                return ApiResult.fail(ProductErrorCode.COMMODITY_NOT_EXISTED);
            }
            if (CommodityShelfStatus.ONLINE.equals(CommodityShelfStatus.getEnum(addtion.getShelfStatus()))) {
                return ApiResult.fail(ProductErrorCode.COMMODITY_UPDATE_ONLINE);
            }
            if (CommodityStatus.USED.equals(CommodityStatus.getEnum(addtion.getStatus()))) {
                return ApiResult.fail(ProductErrorCode.COMMODITY_UPDTAE_USED);
            }
            String oldCommodityCategoryId = addtion.getCommodityCategoryId();
            addtion.setImagesUrl(commodityDto.getImagesUrl());
            addtion.setDetailImagesUrl(JsonUtils.objectToJson(commodityDto.getDetailImagesUrl()));
            addtion.setInitialPurchaseAmount(commodityDto.getInitialPurchaseAmount());
            addtion.setDiscountPrice(commodityDto.getDiscountPrice());
            addtion.setCommodityCategoryId(commodityDto.getCommodityCategoryId());
            addtion.setCommodityCategoryLabel(commodityDto.getCommodityCategoryLabel());
            if (!CollectionUtils.isEmpty(commodityDto.getTags())) {
                addtion.setTag(JsonUtils.objectToJson(commodityDto.getTags()));
            }
            if (!CollectionUtils.isEmpty(commodityDto.getSuitablePeople())) {
                addtion.setSuitablePeople(JsonUtils.objectToJson(commodityDto.getSuitablePeople()));
            }
            if (!CollectionUtils.isEmpty(commodityDto.getSuitableSex())) {
                addtion.setSuitableSex(JsonUtils.objectToJson(commodityDto.getSuitableSex()));
            }
            addtion.setAfterSaleProtection(commodityDto.getAfterSaleProtection());
            addtion.setUpdateDateTime(new Date());
            addtion.setRemarks(commodityDto.getRemarks());
            ApiResult<GeneticTestingPackage> packageResult = productService.updateProduct(commodityDto.getPackageInfo
                    ());
            if (packageResult.isSucc()) {
                // 更新商品信息
                commodityRepository.updateCommodity(addtion);
                if (!commodityDto.getCommodityCategoryId().equals(oldCommodityCategoryId)) {
                    // 当前商品切换类目时，更新商品类目使用情况，原类目使用数量-1，新类目使用数量+1
                    commodityCategoryService.updateCategoryUsedCount(oldCommodityCategoryId, false);
                    commodityCategoryService.updateCategoryUsedCount(commodityDto.getCommodityCategoryId(), true);
                }
            } else {
                return ApiResult.fail(packageResult.getError());
            }
        }
        return ApiResult.succ();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<NullObject> addCommodity(GeneticTestingCommodityDetailDto commodityDto) {
        // 参数校验
        FieldChecker.checkEmpty(commodityDto, "商品信息");
        ErrorCode errorCode = commodityDto.checkCommonField();
        if (errorCode != null) {
            return ApiResult.fail(errorCode);
        }
        // 商品类目校验
        ApiResult<GeneticCommodityCategory> categoryApiResult = commodityCategoryService.getById(commodityDto
                .getCommodityCategoryId());
        if (!categoryApiResult.isSucc()) {
            return ApiResult.fail(categoryApiResult.getError());
        }
        GeneticCommodityCategory category = categoryApiResult.getData();
        if (category == null || !DeleteFlagType.NOT_DELETED.equals(DeleteFlagType.getEnum(category.getDeleteFlag()))) {
            return ApiResult.fail(ProductErrorCode.COMMODITY_CATEGORY_NOT_EXISTED);
        }
        commodityDto.setCommodityCategoryLabel(category.getCategory());
        // 保存套餐信息
        ApiResult<GeneticTestingPackage> packageApiResult = productService.addProduct(commodityDto.getPackageInfo());
        if (!packageApiResult.isSucc()) {
            return ApiResult.fail(packageApiResult.getError());
        }
        // 新增商品信息
        GeneticTestingPackageAddtion addtion = new GeneticTestingPackageAddtion();
        BeanUtils.copyProperties(commodityDto, addtion);
        addtion.setId(UUID32.randomUUIDString());
        addtion.setPackageId(commodityDto.getPackageInfo().getId());
        addtion.setDetailImagesUrl(JsonUtils.objectToJson(commodityDto.getDetailImagesUrl()));
        if (!CollectionUtils.isEmpty(commodityDto.getTags())) {
            addtion.setTag(JsonUtils.objectToJson(commodityDto.getTags()));
        }
        addtion.setRealPurchaseAmount(0);
        addtion.setShoppingCartAmount(0);
        addtion.setViews(0);
        addtion.setCreateDateTime(new Date());
        addtion.setFavorableRate(100);
        addtion.setStatus(CommodityStatus.NON_USED.getCode());
        addtion.setShelfStatus(CommodityShelfStatus.OFFLINE.getCode());
        addtion.setDeleteFlag(DeleteFlagType.NOT_DELETED.getCode());
        commodityRepository.saveCommodity(addtion);
        // 更新商品使用次数
        commodityCategoryService.updateCategoryUsedCount(category.getId(), true);

        return ApiResult.succ();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<NullObject> deleteCommodity(String packageId) {
        FieldChecker.checkEmpty(packageId, "商品套餐id");
        // 商品状态校验
        GeneticTestingPackageAddtion addtion = commodityRepository.findByPackageId(packageId);
        if (addtion == null || DeleteFlagType.DELETE.equals(DeleteFlagType.getEnum(addtion.getDeleteFlag()))) {
            return ApiResult.fail(ProductErrorCode.COMMODITY_NOT_EXISTED);
        }
        if (CommodityShelfStatus.ONLINE.equals(CommodityShelfStatus.getEnum(addtion.getShelfStatus()))) {
            return ApiResult.fail(ProductErrorCode.COMMODITY_DELETE_ONLINE);
        }
        if (CommodityStatus.USED.equals(CommodityStatus.getEnum(addtion.getStatus()))) {
            return ApiResult.fail(ProductErrorCode.COMMODITY_DELETE_USED);
        }
        // 删除商品关联套餐
        ApiResult<GeneticTestingPackage> packageDeleteResult = productService.deletePackageById(packageId);
        if (!packageDeleteResult.isSucc()) {
            return ApiResult.fail(packageDeleteResult.getError());
        }
        // 删除商品，刷新商品关联商品类目使用情况
        addtion.setDeleteFlag(DeleteFlagType.DELETE.getCode());
        addtion.setUpdateDateTime(new Date());
        commodityRepository.updateCommodity(addtion);
        commodityCategoryService.updateCategoryUsedCount(addtion.getCommodityCategoryId(), false);

        return ApiResult.succ();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<NullObject> deleteCommodities(List<String> packageIds) {
        packageIds.forEach(packageId -> {
            ApiResult<NullObject> deleteResult = deleteCommodity(packageId);
            if (!deleteResult.isSucc()) {
                throw new IllegalStateException("商品删除失败：" + deleteResult.getDesc());
            }
        });

        return ApiResult.succ();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<NullObject> shelfCommodity(String packageId, boolean isShelf) {
        FieldChecker.checkEmpty(packageId, "商品套餐id");
        // 商品状态校验
        GeneticTestingPackageAddtion addtion = commodityRepository.findByPackageId(packageId);
        if (addtion == null || DeleteFlagType.DELETE.equals(DeleteFlagType.getEnum(addtion.getDeleteFlag()))) {
            return ApiResult.fail(ProductErrorCode.COMMODITY_NOT_EXISTED);
        }
        // 上架已下架的商品 || 下架上架中的商品
        if (isShelf ^ CommodityShelfStatus.ONLINE.equals(CommodityShelfStatus.getEnum(addtion.getShelfStatus()))) {
            addtion.setShelfStatus(isShelf ? CommodityShelfStatus.ONLINE.getCode() : CommodityShelfStatus.OFFLINE
                    .getCode());
            addtion.setUpdateDateTime(new Date());
            commodityRepository.updateCommodity(addtion);
        }
        return ApiResult.succ();
    }
}
